import { computed, ref, watch, type Ref } from 'vue'
import type { CouponCoreInfo } from '@/types/response/coupon'
import type { CartItemVO } from '@/types/response/shopping-cart'
import { CouponApplicationType } from '@/enum/CouponApplicationType'
import { CouponType } from '@/enum/CouponType'
import Coupon from '@/types/entity/Coupon'
import CouponBatch from '@/types/entity/CouponBatch'
class DiscountedDish {
  dishId: number
  discountAmount: number
  constructor(dishId: number, discountAmount: number) {
    this.dishId = dishId
    this.discountAmount = discountAmount
  }
}

// == 优惠券选择模式上下文 ==
export default function selectModeContext(
  query: {
    selectableBatchIds?: string
    availablePreferentialAmount?: string
    shopId?: number
    selected?: string
  },
  coupons: Ref<CouponCoreInfo[] | undefined>,
  requestShoppingCart?: () => Promise<CartItemVO[]>
) {
  const shoppingCart = ref<CartItemVO[]>()
  if (requestShoppingCart != null && query?.shopId != null) {
    requestShoppingCart().then((_shoppingCart) => (shoppingCart.value = _shoppingCart))
  }
  const _selectableBatchIds = ref<string[] | undefined>(
    query.selectableBatchIds ? Object.values(JSON.parse(query.selectableBatchIds)) : undefined
  )
  const isSelectMode = ref(query.availablePreferentialAmount != undefined)
  const noSelectAnyCouponAvailablePreferentialAmount = ref(
    query.availablePreferentialAmount ? parseFloat(query.availablePreferentialAmount) : undefined
  )
  // 已选择的优惠券与对应的优惠金额
  const selectedCouponIdDiscountAmountMap = ref<{ [key: string]: number }>({})
  // 已选择的折扣优惠券与对应的优惠菜品
  const selectedCouponDiscountDishIdMap = ref<{ [key: string]: number }>({})
  // 已折扣的菜品和其折扣的次数
  const selectedCouponDiscountCountMap = ref<{ [key: string]: number }>({})
  // 已选择的优惠券
  const selectedCoupons = computed(() => {
    const sids = Object.keys(selectedCouponIdDiscountAmountMap.value)
      .map((couponId) => {
        if (coupons.value == null) return null
        return coupons.value.find((coupon) => String(coupon.id) === couponId)
      })
      .filter((coupon) => coupon != null)
    console.log('当前选中：', sids)
    return sids
  })
  // 已折扣的菜品
  const discountedDishes = computed(() => Object.values(selectedCouponDiscountDishIdMap))
  // 取消选中
  function deselect(coupon: CouponCoreInfo) {
    delete selectedCouponIdDiscountAmountMap.value[coupon.id]
    if (coupon.type === CouponType.DISCOUNT_COUPON) {
      const dishId = selectedCouponDiscountDishIdMap.value[coupon.id]
      const count = selectedCouponDiscountCountMap.value[dishId!]
      if (count === 1) {
        delete selectedCouponDiscountCountMap.value[dishId]
      } else {
        selectedCouponDiscountCountMap.value[dishId]--
      }
      delete selectedCouponDiscountDishIdMap.value[coupon.id]
    }
  }
  // 清理所有选中
  function clearSelected() {
    selectedCouponIdDiscountAmountMap.value = {}
    selectedCouponDiscountDishIdMap.value = {}
    selectedCouponDiscountCountMap.value = {}
  }
  // 添加到选中
  function addToSelection(coupon: CouponCoreInfo, discountAmount: number, dishId?: number) {
    if (coupon.type === CouponType.DISCOUNT_COUPON && dishId == null) return
    selectedCouponIdDiscountAmountMap.value[coupon.id] = discountAmount
    if (coupon.type === CouponType.DISCOUNT_COUPON) {
      if (dishId != null) {
        selectedCouponDiscountDishIdMap.value[coupon.id] = dishId
        const count = selectedCouponDiscountCountMap.value[dishId]
        if (count === undefined) {
          selectedCouponDiscountCountMap.value[dishId] = 1
        } else {
          selectedCouponDiscountCountMap.value[dishId]++
        }
      }
    }
  }
  // 本订单不可用的优惠券
  const unAvailableCoupons = computed(() => {
    if (coupons.value == null) return []
    return coupons.value.filter((coupon) => !_selectableBatchIds.value?.includes(coupon.batchId + ''))
  })
  const availableCoupons = computed(() => {
    if (coupons.value == null) return []
    return isSelectMode.value
      ? coupons.value.filter((coupon) => _selectableBatchIds.value?.includes(coupon.batchId + ''))
      : coupons.value
  })
  const currentSelectedPreferentialAmount = computed(() =>
    selectedCoupons.value.reduce((pre, cur) => pre + (cur.parValue + (cur.expansionAmount ?? 0)), 0)
  )
  // 实时的可优惠价格
  const currentAvailablePreferentialAmount = computed(
    () => (noSelectAnyCouponAvailablePreferentialAmount.value ?? 0) - currentSelectedPreferentialAmount.value
  )
  // 寻找折扣券可以应用的菜品
  function findApplicableDishes(coupon: CouponCoreInfo) {
    return shoppingCart.value?.filter((dish) => {
      if (coupon.applicableType === CouponApplicationType.NO_LIMIT) {
        return true
      } else if (coupon.applicableType === CouponApplicationType.APPLICABLE_CATEGORY) {
        if (coupon.applicableValues.split(',')?.includes(String(dish.dishCategoryId))) return true
      } else if (coupon.applicableType === CouponApplicationType.APPLICABLE_GOODS) {
        if (coupon.applicableValues.split(',')?.includes(String(dish.id))) return true
      }
      return false
    })
  }
  /**
   *
   * @param coupon 是可被折扣券折扣的菜品列表
   * @param currentAvailablePreferentialAmount 订单菜品总价剩余可被折扣的金额
   */
  function findHighestDiscountDish(
    applicableShoppingCart: CartItemVO[] | undefined,
    coupon: CouponCoreInfo,
    currentAvailablePreferentialAmount: number
  ) {
    if (coupon == null || applicableShoppingCart == null) return null
    // 对coupon进行降序排序
    const orderedDishList = applicableShoppingCart.sort((a, b) => b.nowPrice - a.nowPrice)
    // 寻找合适的可折扣菜品
    for (const dish of orderedDishList) {
      // 优惠金额
      const priceAfterDiscount = parseFloat(
        (dish.nowPrice - dish.nowPrice * CouponBatch.discountRate(coupon.parValue)).toFixed(2)
      )
      if (!discountedDishes.value.includes(dish.id) && priceAfterDiscount <= priceAfterDiscount)
        return new DiscountedDish(dish.id, priceAfterDiscount)
    }
    return null
  }
  // 寻找折扣券最佳折扣金额
  function findBestDiscountAmount(coupon: CouponCoreInfo): DiscountedDish | null {
    return findHighestDiscountDish(findApplicableDishes(coupon), coupon, currentAvailablePreferentialAmount.value)
  }

  // 方法部分
  // 判断给定的coupon是否满足下次可选
  function isNextTimeClickable(coupon: CouponCoreInfo) {
    // 如果已经选中，那点击可以取消
    if (isChecked(coupon.id)) return true
    // 如果不在，那需要判断是否满足下次可选
    if (coupon.type === CouponType.DISCOUNT_COUPON && findBestDiscountAmount(coupon) != null) {
      return true
    }
    const currentCouponAvailablePreferentialAmount = coupon.parValue + (coupon.expansionAmount ?? 0)
    return currentCouponAvailablePreferentialAmount <= currentAvailablePreferentialAmount.value
  }
  // 是否选择了优惠券
  function isChecked(id: number) {
    return selectedCoupons.value.find((coupon) => coupon.id === id) != null
  }
  function select(coupon: CouponCoreInfo) {
    // 如果已经选择取消
    if (isChecked(coupon.id)) {
      deselect(coupon)
      return
    }
    // 如果没有选择,看能不能选择
    if (!isNextTimeClickable(coupon)) {
      uni.showToast({ title: '该券不可选', icon: 'none' })
      return
    }
    // 如果是不可叠加券 || 选择的是可叠加券，但当前已经有选择了不可叠加券，置空
    if (!coupon.isStackable || selectedCoupons.value.some((c) => !c.isStackable)) clearSelected()
    if (coupon.type === CouponType.CASH_COUPON) {
      addToSelection(coupon, coupon.parValue)
    } else {
      const discountedDish = findBestDiscountAmount(coupon)
      if (discountedDish == null) return
      addToSelection(coupon, discountedDish.discountAmount, discountedDish.dishId)
    }
  }
  // 回显默认选中（checked）
  watch(
    () => availableCoupons.value,
    (newVal, oldVal) => {
      if (oldVal.length === 0 && newVal.length > 0) {
        if (query.selected != null) {
          const defaultSelectedCoupons: number[] = JSON.parse(query.selected)
          // 检查selected中的是否都在可以选中的
          if (
            defaultSelectedCoupons.find((id) => !availableCoupons.value.map((item) => item.id)?.includes(id)) == null
          ) {
            // 到这里说明预选的都存在于可选列表中
            for (const couponId of defaultSelectedCoupons) {
              const coupon = availableCoupons.value.find((coupon) => coupon.id === couponId)
              console.log('准备选中：', coupon)
              if (coupon == null) break
              select(coupon)
            }
          }
        }
      }
    }
  )

  // 返回方法和状态
  return {
    selectableBatchIds: _selectableBatchIds,
    isSelectMode,
    noSelectAnyCouponAvailablePreferentialAmount,
    coupons,
    selectedCoupons,
    unAvailableCoupons,
    availableCoupons,
    currentSelectedPreferentialAmount,
    currentAvailablePreferentialAmount,
    isNextTimeClickable,
    isChecked,
    select,
    clearSelectedCoupons: clearSelected,
    findBestDiscountAmount
  }
}
